<template>
  <transition name="fade">
    <div
        v-if="visible"
        class="back-to-top"
        :style="computedStyle"
        role="button"
        tabindex="0"
        aria-label="返回顶部"
        @click="handleClick"
        @keydown="handleKeydown"
    >
      <slot>
        <el-icon :size="iconSize" class="icon">
          <ArrowUp />
        </el-icon>
      </slot>
      <!-- 光晕脉冲 -->
      <span class="aura" aria-hidden="true"></span>
      <!-- 点击涟漪：通过动态 class 控制动画 -->
      <span class="ripple" v-if="rippling" aria-hidden="true"></span>
    </div>
  </transition>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { ElIcon } from 'element-plus'
import { ArrowUp } from '@element-plus/icons-vue'

const props = defineProps({
  threshold: { type: Number, default: 300 },          // 显示按钮的滚动距离
  duration: { type: Number, default: 500 },           // 回顶动画时长（ms）
  right: { type: String, default: '20px' },           // 右侧距离
  bottom: { type: String, default: '40px' },          // 下侧距离（会叠加安全区）
  size: { type: Number, default: 48 },                // 按钮尺寸（px）
  iconSize: { type: Number, default: 22 },            // 图标尺寸（px）
  color: { type: String, default: '#2F88FF' },        // 主题色（用于光晕/涟漪）
  bgColor: { type: String, default: 'rgba(30, 30, 30, 0.6)' }, // 背景色（玻璃拟态）
  blur: { type: Number, default: 10 },                // 背景模糊强度
})

const visible = ref(false)
const rippling = ref(false)

const computedStyle = computed(() => ({
  position: 'fixed',
  right: `max(${props.right}, env(safe-area-inset-right))`,
  bottom: `calc(${props.bottom} + env(safe-area-inset-bottom))`,
  width: `${props.size}px`,
  height: `${props.size}px`,
  cursor: 'pointer',
  zIndex: 9999,
  // 视觉：玻璃拟态 + 圆形
  background: props.bgColor,
  color: '#fff',
  borderRadius: '50%',
  backdropFilter: `blur(${props.blur}px)`,
  WebkitBackdropFilter: `blur(${props.blur}px)`,
  boxShadow:
      '0 8px 24px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.12), 0 0 0 1px rgba(255,255,255,0.06)',
  transition:
      'transform 180ms ease, opacity 180ms ease, box-shadow 180ms ease, background 200ms ease',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  // 提前设置 CSS 变量供样式使用
  '--theme': props.color,
}))

const handleScroll = () => {
  visible.value = window.scrollY > props.threshold
}

const easeOutCubic = (t) => (--t) * t * t + 1

const scrollToTop = () => {
  const start = window.scrollY
  const startTime = performance.now()
  const duration = props.duration

  const animateScroll = (currentTime) => {
    const elapsed = currentTime - startTime
    const progress = Math.min(elapsed / duration, 1)

    // 用户偏好减少动效时，跳过动画
    const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
    if (prefersReduced) {
      window.scrollTo({ top: 0, behavior: 'instant' })
      return
    }

    window.scrollTo(0, start * (1 - easeOutCubic(progress)))
    if (progress < 1) requestAnimationFrame(animateScroll)
  }

  requestAnimationFrame(animateScroll)
}

const handleClick = () => {
  // 触发涟漪动画
  rippling.value = true
  // 下一帧执行回顶，保证涟漪显示
  requestAnimationFrame(() => {
    scrollToTop()
  })
  // 动画结束后移除
  setTimeout(() => {
    rippling.value = false
  }, 380)
}

const handleKeydown = (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault()
    handleClick()
  }
}

onMounted(() => {
  // 初始检查 + 使用 passive 提升滚动性能
  handleScroll()
  window.addEventListener('scroll', handleScroll, { passive: true })
})

onUnmounted(() => {
  window.removeEventListener('scroll', handleScroll)
})
</script>

<style scoped>
/* 进出淡入淡出过渡 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 180ms ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

/* 按钮基础与交互动效 */
.back-to-top {
  outline: none;
  will-change: transform, opacity, box-shadow, background;
  /* 轻微的默认缩放，显得紧致 */
  transform: translateZ(0) scale(0.98);
}

/* 悬浮：微缩放 + 上移 + 阴影增强 + 背景略亮 */
.back-to-top:hover {
  transform: translateY(-2px) scale(1.06);
  box-shadow:
      0 12px 28px rgba(0,0,0,0.28),
      inset 0 1px 0 rgba(255,255,255,0.16),
      0 0 0 1px rgba(255,255,255,0.08);
  background: rgba(40, 40, 40, 0.65);
}

/* 点击压感反馈 */
.back-to-top:active {
  transform: translateY(0) scale(0.96);
}

/* 键盘可访问焦点态：环形高亮 */
.back-to-top:focus-visible {
  box-shadow:
      0 0 0 3px rgba(255,255,255,0.22),
      0 0 0 6px color-mix(in srgb, var(--theme) 60%, transparent);
}

/* 图标轻微跃动（悬浮时） */
.icon {
  transition: transform 200ms ease, opacity 200ms ease;
}
.back-to-top:hover .icon {
  transform: translateY(-1px);
  opacity: 0.96;
}

/* 光晕脉冲（持续但克制） */
.aura {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  /* 使用渐变制造层次感的光晕 */
  background:
      radial-gradient(closest-side, color-mix(in srgb, var(--theme) 22%, transparent), transparent 70%)
      center/100% 100% no-repeat;
  animation: auraPulse 2800ms ease-in-out infinite;
  opacity: 0.35;
  filter: blur(6px);
}
@keyframes auraPulse {
  0%, 100% { transform: scale(0.98); opacity: 0.28; }
  50%      { transform: scale(1.06); opacity: 0.42; }
}

/* 点击涟漪（短动画） */
.ripple {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background:
      radial-gradient(circle, color-mix(in srgb, var(--theme) 48%, transparent) 0%,
      transparent 60%);
  animation: rippleBurst 360ms ease-out forwards;
  opacity: 0.7;
  filter: blur(2px);
}
@keyframes rippleBurst {
  0%   { transform: scale(0.2); opacity: 0.8; }
  60%  { transform: scale(1.25); opacity: 0.35; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* 减少动效偏好：禁用复杂动画与脉冲 */
@media (prefers-reduced-motion: reduce) {
  .back-to-top,
  .icon {
    transition: none !important;
  }
  .aura,
  .ripple {
    display: none !important;
  }
}
</style>
